# -*- coding: utf-8 -*-
# created on 2016/12/22
from sympy import sympify, Eq, Add
from mathsolver.functions.base import BaseFunction, BasePoint, BaseValue, BaseEq, new_latex
from mathsolver.functions.hanshu.zhouqi import is_faxplusb_anyb
from mathsolver.functions.sympy_utils import get_all_child, default_symbol


def jiouhanshu_duichengxing(jiou):
    """奇函数、偶函数对称性
    :param jiou 奇函数/偶函数
    :return (0, 0) 或者 x = 0
    """
    if '奇' in jiou:
        res = (0, 0)
    elif '偶' in jiou:
        res = Eq(sympify('x'), 0)
    else:
        raise ValueError('unknown type %s' % jiou)
    return res


def zhongxingduicheng_dingyishi(point):
    """hs062.函数中心对称定义式 - f(x) 关于 point 中心对称"""
    a, b = point
    relation = Eq(sympify('f(2*{a}-x) + f(x)'.format(a=a)), sympify('2*{b}'.format(b=b)))
    step = '由函数关于点 ({a}, {b}) 对称可知对于定义域内的任意 x 均有 {eq}'.format(a=a, b=b, eq=new_latex(relation))
    return relation, step


def zhouduicheng_dingyishi(a):
    """hs063.函数轴对称定义式 - f(x) 关于 x=a 轴对称"""
    relation = Eq(sympify('f(2*{a}-x)'.format(a=a)), sympify('f(x)'))
    step = '由函数关于 x = {a} 对称可知对于定义域内的任意 x 均有 {eq}'.format(a=a, eq=new_latex(relation))
    return relation, step


def zhongxingduicheng_dingyishi_general(fx, point):
    """函数中心对称定义式 - f(ax+b) 关于 point 中心对称"""
    c, d = point
    sym = default_symbol(fx)
    fx_dingyi = 2 * d - fx.subs(sym, 2 * c - sym)
    res = Eq(fx, fx_dingyi)
    step = '由函数关于点 (%s, %s) 对称可知对于定义域内的任意 x 均有 %s' % (c, d, new_latex(res))
    return res, step


def zhouduicheng_dingyishi_general(fx, c):
    """函数中心对称定义式 - f(ax+b) 关于 x=c 中心对称"""
    sym = default_symbol(fx)
    fx_dingyi = - fx.subs(sym, 2 * c - sym)
    res = Eq(fx, fx_dingyi)
    step = '由函数关于 x = %s 对称可知对于定义域内的任意 x 均有 %s' % (c, new_latex(res))
    return res, step


def dingyishi_qiu_duichengzhongxing(eq):
    """hs064.定义式确定函数对称中心
    输入 f(a*x+b) + f(c*x+d) = m, a+c = 0 => ((b+d)/2, m/2)
    """
    # 处理输入
    expr = eq.lhs - eq.rhs
    f_exprs = get_all_child(expr, is_faxplusb_anyb)
    m = Add(*f_exprs) - expr
    ((a, b), (c, d)) = [is_faxplusb_anyb(f_expr) for f_expr in f_exprs]

    if a == -c:
        zhongxing = ((b + d) / 2, m / 2)
        step = '由 %s 求出函数 f(x) 的对称中心为 %s' % (new_latex(eq), zhongxing)
    else:
        raise ValueError('unknown value {}'.format(new_latex(eq)))
    return zhongxing, step


def dinyishi_qiu_duichengzhou(eq):
    """hs065.定义式确定函数对称轴
    输入 f(a*x+b) = f(c*x+d), a+c = 0 => (b+d)/2
    """
    expr = eq.lhs - eq.rhs
    f_exprs = get_all_child(expr, is_faxplusb_anyb)
    ((a, b), (c, d)) = [is_faxplusb_anyb(f_expr) for f_expr in f_exprs]

    if a == -c:
        duichengzhou = (b + d) / 2
    else:
        raise ValueError('unknown value {}'.format(new_latex(eq)))

    step = '由 %s 求出函数 f(x) 的对称轴为 x = %s' % (new_latex(eq), duichengzhou)
    return duichengzhou, step


class DingYiShiQiuDuiChengXing(BaseFunction):
    """032.定义式确定函数对称性"""

    def solver(self, *args):
        left, right = sympify(args[0].value)
        expr = left - right
        f_exprs = get_all_child(expr, is_faxplusb_anyb)

        if (expr - Add(*f_exprs)).has(default_symbol(expr)):
            # 对称轴类型
            relation, step = dinyishi_qiu_duichengzhou(Eq(expr, 0))
        else:
            # 对称中心
            relation, step = dingyishi_qiu_duichengzhongxing(Eq(expr, 0))

        self.steps.append(["", step])
        self.output.append(BaseValue(relation))
        self.label.add("定义式确定函数对称性")
        return self


class BianHuanQiuDuiCheng(BaseFunction):
    """033.函数变换后对称中心
    已知 y = f(mx+n) + k1 对称中心为 (a, b), 求 y = f(px+q) + k2 的对称中心
    """

    def solver(self, *args):
        # 处理输入
        eq1, point, eq2 = args
        # 提取出 a, b
        a, b = sympify(point.value)

        # 提取出 m, n, k1
        expr1 = sympify(eq1.value[1])
        f_expr = get_all_child(expr1, is_faxplusb_anyb)[0]
        k1 = expr1 - f_expr
        m, n = is_faxplusb_anyb(f_expr)

        # 提取出 p, q, k2
        expr2 = sympify(eq2.value[1])
        f_expr2 = get_all_child(expr2, is_faxplusb_anyb)[0]
        k2 = expr2 - f_expr2
        p, q = is_faxplusb_anyb(f_expr2)

        res = ((m * a + b - q) / p, k2 - k1)
        self.steps.append(["", "函数 %s 的对称中心为 %s，则 y = f(x) 的对称中心为 (%s, %s)" %
                           (eq1.printing(), point.printing(), m * a + n, -k1)])
        self.steps.append(["", "从而求得 %s 的对称中心为 %s" % (eq2.printing(), res)])

        self.label.add("函数变换后对称中心")
        self.output.append(BasePoint({'name': '', 'value': res}))
        return self


class BianHuanQiuDuiChengZhou(BaseFunction):
    """033.函数变换后对称轴
    已知 y = f(mx+n) + k1 对称中心为 x=a, 求 y = f(px+q) + k2 的对称轴
    """

    def solver(self, *args):
        # 处理输入
        eq1, eq, eq2 = args
        # 提取出 a, b
        a = sympify(eq.value[1])

        # 提取出 m, n, k1
        expr1 = sympify(eq1.value[1])
        f_expr = get_all_child(expr1, is_faxplusb_anyb)[0]
        m, n = is_faxplusb_anyb(f_expr)

        # 提取出 p, q, k2
        expr2 = sympify(eq2.value[1])
        f_expr2 = get_all_child(expr2, is_faxplusb_anyb)[0]
        p, q = is_faxplusb_anyb(f_expr2)

        res = (m * a + n - q) / p
        self.steps.append(["", "函数 %s 的对称轴为 %s，则 y = f(x) 的对称轴为 x = %s" %
                           (eq1.printing(), eq.printing(), m * a + n)])
        self.steps.append(["", "从而求得 %s 的对称轴为 x = %s" % (eq2.printing(), res)])

        self.label.add("函数变换后对称中心")
        self.output.append(BaseValue(BaseEq(['x', res])))
        return self


if __name__ == '__main__':
    pass
